﻿using ELearning.BLL;
using ELearning.Common.Model;
using ELearning.Models;
using ELearning.Models.ViewModel.Role;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using System.Web.Http;
using ELearning.Common;
using ELearning.Common.Extensions;
using ELearning.Common.Helpers;
using ELearning.Models.ViewModel.User;

namespace ELearning.API.Controllers
{
    /// <inheritdoc />
    /// <summary>
    /// 角色控制器
    /// </summary>
    public class RoleController : BaseApiController
    {
        /// <summary>
        /// 角色操作service
        /// </summary>
        protected ERoleService RoleService = new ERoleService();

        /// <summary>
        /// 角色菜单关联操作service
        /// </summary>
        protected RMenuURService RMenuURService = new RMenuURService();

        /// <summary>
        /// 角色用户管理操作service
        /// </summary>
        private RRoleUserService rRoleUserService = new RRoleUserService();

        /// <summary>
        /// 用户操作service
        /// </summary>
        protected ESysUserService userService = new ESysUserService();
        
        /// <summary>
        /// 获取角色列表
        /// </summary>
        /// <param name="request">接口参数，包括分页以及查询参数</param>
        /// <returns>角色列表</returns>
        [HttpPost, Route("api/erole/GetRoleList")]
        public ServiceResponse<RoleViewModel> GetRoleList(GetRoleRequest request)
        {
            var viewModel = new RoleViewModel();
            Expression<Func<ERole, bool>> whereLamdba = (u) => u.IsDelete == false && u.ParentID == Guid.Empty;
            if (!string.IsNullOrEmpty(request.RoleName))
                whereLamdba = whereLamdba.And(u => u.RoleName.Contains(request.RoleName));
            if (!string.IsNullOrEmpty(request.Type))
                whereLamdba = whereLamdba.And(u => u.Type.Equals(request.Type));
            var modelList = RoleService.FindList(whereLamdba).ToList();
            if (modelList.Any())
            {
                viewModel.Total = modelList.Count();
                var roleIds = modelList.Select(r => r.RoleID).ToList();
                var rms = RMenuURService.FindList(rm => roleIds.Contains(rm.KeyId) && !rm.IsDelete && !rm.IsHalfChecked).ToList();
                GetViewModels(viewModel.Items, modelList, rms, Guid.Empty, new List<Guid>());
            }
            return ServiceResponse<RoleViewModel>.SuccessResponse("success", viewModel);
        }

        /// <summary>
        /// 构造层级角色
        /// </summary>
        private void GetViewModels(List<RoleItem> items, List<ERole> models, List<RMenuUR> rms, Guid parentId, List<Guid> fullMenuIdList)
        {
            var subList = models.Where(m => m.ParentID == parentId).ToList();
            var pModel = models.Find(m => m.RoleID == parentId);
            foreach (var role in subList)
            {
                var viewModel = new RoleItem
                {
                    id = role.RoleID,
                    Code = role.Code,
                    CreateTime = role.CreateTime,
                    OrgCode = role.OrgCode ?? string.Empty,
                    Creater = role.Creater,
                    IsDelete = role.IsDelete,
                    RoleName = role.RoleName,
                    Text = role.Text,
                    ParentID = role.ParentID,
                    Type = role.Type,
                    ParentName = pModel?.RoleName ?? "用户角色"
                };
                var ts = rms.Where(r => r.KeyId == role.RoleID).ToList();
                foreach (var t in ts)
                {
                    viewModel.MenuIdList.Add(t.MenuId);
                }

                viewModel.FullMenuIdList.AddRange(fullMenuIdList);
                viewModel.FullMenuIdList.AddRange(viewModel.MenuIdList);
                GetViewModels(viewModel.children, models, rms, viewModel.id, viewModel.FullMenuIdList);

                if (!viewModel.children.Any())
                    viewModel.children = null;
                items.Add(viewModel);
            }
        }

        /// <summary>
        /// 分配角色弹窗--获取角色列表
        /// </summary>
        [HttpGet, Route("api/erole/GetDialogRoleList")]
        public ServiceResponse<RoleViewModel> GetDialogRoleList()
        {
            var viewModel = new RoleViewModel();
            Expression<Func<ERole, bool>> whereLamdba = (u) => u.IsDelete == false;
            var modelList = RoleService.FindList(whereLamdba).ToList();
            if (modelList.Any())
            {
                viewModel.Total = modelList.Count();
                var roleIds = modelList.Select(r => r.RoleID).ToList();
                var rms = RMenuURService.FindList(rm => roleIds.Contains(rm.KeyId) && !rm.IsDelete && !rm.IsHalfChecked).ToList();
                GetViewModels(viewModel.Items, modelList, rms, Guid.Empty, new List<Guid>());
            }
            return ServiceResponse<RoleViewModel>.SuccessResponse("success", viewModel);
        }

        /// <summary>
        /// 获取角色下面的所有子节点
        /// </summary>
        [HttpGet, Route("api/erole/GetRoleSubList")]
        public ServiceResponse<RoleViewModel> GetRoleSubList(Guid id)
        {
            var viewModel = new RoleViewModel();
            var modelList = RoleService.GetRoleSubList(id).ToList();
            var roleIds = modelList.Select(r => r.RoleID).ToList();
            var rms = RMenuURService.FindList(rm => roleIds.Contains(rm.KeyId) && !rm.IsDelete && !rm.IsHalfChecked).ToList();
            GetViewModels(viewModel.Items, modelList, rms, Guid.Empty, new List<Guid>());
            return ServiceResponse<RoleViewModel>.SuccessResponse("success", viewModel);
        }

        /// <summary>
        /// 获取当前用户的角色列表
        /// </summary>
        [HttpGet, Route("api/erole/GetUserRoleList")]
        public ServiceResponse<List<string>> GetUserRoleList()
        {
            var ls = RoleService.FindList(r => !r.IsDelete).Select(r => r.RoleName).ToList();
            return ServiceResponse<List<string>>.SuccessResponse("success", ls);
        }

        /// <summary>
        /// 获取所有的角色列表
        /// </summary>
        [HttpGet, Route("api/erole/GetAllRoleList")]
        public ServiceResponse<List<ERole>> GetAllRoleList()
        {
            var ls = RoleService.FindList(r => !r.IsDelete).ToList();
            return ServiceResponse<List<ERole>>.SuccessResponse("success", ls);
        }

        /// <summary>
        /// 添加角色
        /// </summary>
        /// <param name="o">角色相关信息包括选择的权限id列表</param>
        [HttpPost, Route("api/erole/AddRole")]
        public ServiceResponse<RoleItem> AddRole(RoleItem o)
        {
            var role = new ERole
            {
                RoleID = GuidUtil.NewSequentialId(),
                CreateTime = DateTime.Now,
                Code = o.Code,
                Creater = CurrentUserModel.LoginName,
                IsDelete = false,
                ModifyTime = DateTime.Now,
                RoleName = o.RoleName,
                Text = o.Text,
                ParentID = o.ParentID,
                Type = o.Type,
                OrgCode = o.OrgCode
            };

            var fullSpell = PinYinHelper.ConvertToAllSpell(role.RoleName);//菜单全拼
            var firstSpell = PinYinHelper.GetFirstSpell(role.RoleName);//菜单首拼
            var model = RoleService.Find(m => !m.IsDelete && m.Code.Equals(firstSpell, StringComparison.InvariantCultureIgnoreCase));
            if (model != null)
            {
                model = RoleService.Find(m => !m.IsDelete && m.Code.Equals(fullSpell, StringComparison.InvariantCultureIgnoreCase));
                if (model != null)
                {
                    role.Code = $"{firstSpell}{DateTime.Now:yyMMddHHmmss}";
                }
                else
                {
                    role.Code = fullSpell;
                }
            }
            else
            {
                role.Code = firstSpell;
            }

            RoleService.Add(role);

            //插入新的关联关系
            var urList = new List<RMenuUR>();
            foreach (var menuId in o.MenuIdList)
            {
                var urModel = new RMenuUR
                {
                    IsDelete = false,
                    IsUsed = true,
                    Id = GuidUtil.NewSequentialId(),
                    KeyId = role.RoleID,
                    MenuId = menuId,
                    IsHalfChecked = false,
                    CreateTime = DateTime.Now
                };
                urList.Add(urModel);
            }
            foreach (var menuId in o.HalfMenuIdList)
            {
                var urModel = new RMenuUR
                {
                    IsDelete = false,
                    IsUsed = true,
                    Id = GuidUtil.NewSequentialId(),
                    KeyId = role.RoleID,
                    MenuId = menuId,
                    IsHalfChecked = true,
                    CreateTime = DateTime.Now
                };
                urList.Add(urModel);
            }
            RMenuURService.Adds(urList);

            return ServiceResponse<RoleItem>.SuccessResponse(o);
        }

        /// <summary>
        /// 更新角色
        /// </summary>
        [HttpPost, Route("api/erole/UpdateRole")]
        public ServiceResponse<RoleItem> UpdateRole(RoleItem o)
        {
            var role = RoleService.Find(r => !r.IsDelete && r.RoleID == o.id);
            role.Code = o.Code;
            role.OrgCode = o.OrgCode;
            role.ParentID = o.ParentID;
            role.ModifyTime = DateTime.Now;
            role.RoleName = o.RoleName;
            role.Text = o.Text;
            RoleService.Update(role);
            //删除掉原来的关联
            var rs = RMenuURService.FindList(r => !r.IsDelete && r.KeyId == o.id).ToList();
            RMenuURService.Deletes(rs);

            //插入新的关联关系
            var urList = new List<RMenuUR>();
            foreach (var menuId in o.MenuIdList)
            {
                var urModel = new RMenuUR
                {
                    IsDelete = false,
                    IsUsed = true,
                    Id = GuidUtil.NewSequentialId(),
                    KeyId = role.RoleID,
                    MenuId = menuId,
                    IsHalfChecked = false,
                    CreateTime = DateTime.Now
                };
                urList.Add(urModel);
            }
            foreach (var menuId in o.HalfMenuIdList)
            {
                var urModel = new RMenuUR
                {
                    IsDelete = false,
                    IsUsed = true,
                    Id = GuidUtil.NewSequentialId(),
                    KeyId = role.RoleID,
                    MenuId = menuId,
                    IsHalfChecked = true,
                    CreateTime = DateTime.Now
                };
                urList.Add(urModel);
            }
            RMenuURService.Adds(urList);

            return ServiceResponse<RoleItem>.SuccessResponse(o);
        }

        /// <summary>
        /// 删除角色
        /// </summary>
        /// <param name="id">角色id</param>
        [HttpPost, Route("api/erole/DeleteRole")]
        public ServiceResponse<int> DeleteRole(Guid id)
        {
            var role = RoleService.Find(r => !r.IsDelete && r.RoleID == id);
            role.IsDelete = true;
            RoleService.Update(role);
            return ServiceResponse<int>.SuccessResponse(1);
        }

        /// <summary>
        /// 获取角色下的用户名称列表
        /// </summary>
        /// <param name="roleId">角色id</param>
        [HttpGet, Route("api/erole/GetRoleUser")]
        public ServiceResponse<List<Guid>> GetRoleUser(Guid roleId)
        {
            var userIds = new List<Guid>();
            var modelList = rRoleUserService.FindList(r => r.RoleID == roleId).ToList();
            if (modelList.Any())
                userIds = modelList.Select(m => m.UserID).ToList();
            return ServiceResponse<List<Guid>>.SuccessResponse(userIds);
        }

        /// <summary>
        /// 角色关联的用户列表或者角色不关联的用户列表
        /// </summary>
        [HttpPost, Route("api/erole/GetRoleUserItems")]
        public ServiceResponse<RoleUserViewModel> GetRoleUserItems(GetRoleUserRequest request)
        {
            var modelList = RoleService.GetRoleUserList(request);
            var viewModel = new RoleUserViewModel
            {
                TotalCount = modelList.FirstOrDefault()?.Total ?? 0
            };
            foreach (var m in modelList)
            {
                var u = m.MapTo<GetUserItem, SysUserModel>();
             
                viewModel.Items.Add(u);
            }

            return ServiceResponse<RoleUserViewModel>.SuccessResponse(viewModel);
        }

        /// <summary>
        /// 获取角色下面的用户列表
        /// </summary>
        [HttpPost, Route("api/erole/GetRoleUserList")]
        public ServiceResponse<GetUserViewModel> GetRoleUserList(RoleUserRequest request)
        {
            var userIds = new List<Guid>();
            var viewModel = new GetUserViewModel();
            Expression<Func<RRoleUser, bool>> whereLamdba = u => u.RoleID == request.RoleId;
            var modelList = rRoleUserService.FindPageList(request.Page, request.PageSize, out var totalRecord, "UserID", "DESC", whereLamdba).ToList();
            if (modelList.Any())
                userIds = modelList.Select(m => m.UserID).ToList();
            if (userIds.Any())
            {
                var userList = userService.FindList(u => userIds.Contains(u.UserID));
                foreach (var user in userList)
                {
                    var u = user.MapTo<GetUserItem, ESysUser>();
                    u.CreateTime = user.CreateTime.ToString("yyyy-MM-dd HH:mm");
                    u.ModifyTime = user.ModifyTime;
                    u.Password = user.Password;
                    u.ConfirmPassword = user.Password;
                    u.Sex = SexHelper.SexToStr(user.Sex);

                    viewModel.UserItems.Add(u);
                }
                viewModel.TotalCount = totalRecord;
            }

            return ServiceResponse<GetUserViewModel>.SuccessResponse(viewModel);
        }

        /// <summary>
        /// 为角色分配用户
        /// </summary>
        [HttpPost, Route("api/erole/HandleRoleUser")]
        public ServiceResponse<bool> HandleRoleUser(HandleRoleUserViewModel viewModel)
        {
            if (viewModel.OprateType == 1)
            {
                var rRoleUsers = new List<RRoleUser>();
                if (viewModel.Users != null && viewModel.Users.Any())
                {
                    foreach (var user in viewModel.Users)
                    {
                        if (user == null)
                            continue;
                        var r = new RRoleUser
                        {
                            ID = GuidUtil.NewSequentialId(),
                            UserID = user.UserId,
                            RoleID = viewModel.RoleId
                        };
                        rRoleUsers.Add(r);
                    }
                }
                rRoleUserService.Adds(rRoleUsers);
            }
            else
            {
                var puIds = viewModel.Users.Select(u => u.UserId).ToList(); //用户id列表
                var deleteList = rRoleUserService.FindList(r => r.RoleID == viewModel.RoleId && puIds.Contains(r.UserID)).ToList();
                if (deleteList.Any())
                    rRoleUserService.Deletes(deleteList);
            }

            return ServiceResponse<bool>.SuccessResponse(true);
        }

        /// <summary>
        /// 指定搜索条件下面的用户授权
        /// </summary>
        [HttpPost, Route("api/erole/HandleBatchRoleUser")]
        public ServiceResponse<bool> HandleBatchRoleUser(GetRoleUserRequest viewModel)
        {
            var users = RoleService.GetBatchRoleUserList(viewModel);
            var userIds = users.Select(u => u.UserID).ToList();
            if (viewModel.ReqestType == 1)
            {
                var rRoleUsers = new List<RRoleUser>();
                if (userIds.Any())
                {
                    foreach (var userId in userIds)
                    {
                        var r = new RRoleUser
                        {
                            ID = GuidUtil.NewSequentialId(),
                            UserID = userId,
                            RoleID = viewModel.RoleId
                        };
                        rRoleUsers.Add(r);
                    }
                    var dt = rRoleUsers.ToDataTable(null);
                    if (string.IsNullOrEmpty(dt.TableName))
                        dt.TableName = "RRoleUser";
                    SqlBulkCopyHelper.SaveTable(dt);
                }
            }
            else
            {
                var deleteList = rRoleUserService.FindList(r => r.RoleID == viewModel.RoleId && userIds.Contains(r.UserID)).ToList();
                var ids = deleteList.Select(r => r.ID).ToList();
                if (deleteList.Any())
                {
                    var page = (ids.Count + 99) / 100;
                    for (var i = 0; i < page; i++)
                    {
                        var dls = ids.Skip(i * 100).Take(100).ToList();
                        rRoleUserService.BatchDelete(dls);
                    }
                }
            }

            return ServiceResponse<bool>.SuccessResponse(true);
        }

        /// <summary>
        /// 获取层次分明的下拉框角色列表
        /// </summary>
        [HttpGet, Route("api/erole/GetAllRoleListWithOptions")]
        public ServiceResponse<List<RoleOptionItem>> GetAllRoleListWithOptions()
        {
            var viewModels = new List<RoleOptionItem>();
            var modelList = RoleService.FindList(r => !r.IsDelete).ToList();
            GenerateAllRoleList(modelList, viewModels, Guid.Empty);

            return ServiceResponse<List<RoleOptionItem>>.SuccessResponse(viewModels);
        }

        private void GenerateAllRoleList(List<ERole> modelList, List<RoleOptionItem> viewModels, Guid pId, int i = 1)
        {
            i++;
            var subList = modelList.Where(l => !l.IsDelete && l.ParentID == pId).OrderBy(l => l.CreateTime).ToList();
            foreach (var role in subList)
            {
                var str = "";
                //父级菜单不缩进  
                for (var j = 1; j < i; j++)
                {
                    str += HttpUtility.HtmlDecode("&nbsp;&nbsp;");
                }
                if (i > 2)
                    str += "├";
                var v = new RoleOptionItem
                {
                    RoleId = role.RoleID,
                    RoleName = $"{str}{role.RoleName}",
                    ParentID = role.ParentID
                };
                viewModels.Add(v);
                GenerateAllRoleList(modelList, viewModels, v.RoleId, i);
            }
        }
    }
}